<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        let data = { msg: '123' }
        let bucket = new WeakMap()
        /*
        理解数据结构：
            1.  bucket -> 里面是 target是键
                target是对象
                    而值是map数据结构
                        map的键是key，也就是target里面的key
                            而target的key对应的值就是set数据结构里面存储了所有的affect副作用域函数
                {
                    target1: {
                        key1: {fn1, fn2},
                        key2: {fn1, fn2}
                    },
                    target2: {
                        key3: {fn3, fn4},
                        key4: {fn5, fn6}
                    }
                }
        */
        // 1.声明weakMap存储数据
        // 2.利用proxy代理
        // 3.get里面track
        // 判断bucket里面是否有target 没有的话就要手动创建关系
        // 判断bucket[target]里面是否有depSet，没有的话手动创建
        // 把全局函数添加进去
        // 4.set里面trigger
        // 触发
        // 全局函数没有值 直接return
        // 判断bucket里面是否有target
        // 判断depMap里面有没有effects
        // 有的话 再去执行
        let activeAffect // 这个是全局变量 存储副作用函数
        let obj = new Proxy(data, {
            get(target, key) {
                track(target, key)
                console.log('访问了', target[key]);
                return target[key]
            },
            set(target, key, newVal) {
                target[key] = newVal
                console.log('修改了', target[key], '为', newVal);
                trigger(target, key)
            }
        })
        function track(target, key) {
            if (!activeAffect) {
                return target[key]
            }
            let depMap = bucket.get(target)
            if (!depMap) {
                bucket.set(target, (depMap = new Map()))
            }
            let depSet = depMap.get(key)
            if (!depSet) {
                depMap.set(key, (depSet = new Set()))
            }
            depSet.add(activeAffect)
        }
        function trigger(target, key) {
            let depMap = bucket.get(target)
            let effects = depMap.get(key)

            effects && effects.forEach(fn => fn())
        }
        function effect(fn) {
            activeAffect = fn
            fn()
        }
        effect(() => {
            document.body.innerHTML = obj.msg
        })

    </script>
</body>

</html>